/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.config.console;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.tianyun.cloud.config.console.annotaion.ConsoleDiscovery;
import org.tianyun.cloud.registrar.BeanRegistrar;

import java.lang.reflect.Method;
import java.util.Set;

/**
 * 扫描ConsoleDiscovery自定义注解收集控制台组件信息
 *
 * @auther ebert_chan
 */
public class ConsoleDiscoveryAnnotationRegistrar extends BeanRegistrar {

    /*
     * @see org.tianyun.cloud.registrar.BeanRegistrar#registerBeanDefinitions()
     */
    @Override
    public void registerBeanDefinitions() {
        Set<String> basePackages = this.getComponentScanningPackages();
        // 注册RedisContainer
        this.registerConsoleComponent(basePackages);
    }

    /**
     * 扫描@RedisContainer注解
     *
     * @param basePackages
     * @auther ebert_chan
     */
    public void registerConsoleComponent(Set<String> basePackages) {
        for (String basePackage : basePackages) {
            registerConsoleComponent(basePackage);
        }
    }

    private void registerConsoleComponent(String basePackage) {
        Set<BeanDefinition> candidateComponents = this.findCandidateComponents(basePackage, Component.class);
        for (BeanDefinition candidateComponent : candidateComponents) {
            if (candidateComponent instanceof AnnotatedBeanDefinition) {
                // verify annotated class is not an interface
                AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
                AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
                if (annotationMetadata.isInterface()) {
                    continue;
                }
                String className = annotationMetadata.getClassName();
                resolveConsoleDiscovery(className);
            }
        }
    }

    private void resolveConsoleDiscovery(String className) {
        Class<?> clazz = this.loadClass(className);
        Method[] methods = ReflectionUtils.getDeclaredMethods(clazz);
        if (methods == null) {
            return;
        }

        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            ConsoleDiscovery consoleDiscovery = AnnotatedElementUtils.findMergedAnnotation(method, ConsoleDiscovery.class);
            if (consoleDiscovery == null) {
                continue;
            }
            String beanName = consoleDiscovery.beanName();
            if (!StringUtils.hasText(beanName)) {
                Bean bean = method.getDeclaredAnnotation(Bean.class);
                if (bean != null) {
                    beanName = this.getFirstValue(bean.value());
                    if (!StringUtils.hasText(beanName)) {
                        beanName = this.getFirstValue(bean.name());
                    }
                }
                if (!StringUtils.hasText(beanName)) {
                    beanName = method.getName();
                }
            }
            if (!StringUtils.hasText(beanName)) {
                continue;
            }
            ConsoleManager.registerComponent(
                    new org.tianyun.cloud.config.console.property.Component(consoleDiscovery.namespace(), beanName, consoleDiscovery.prefix()));
        }
    }


}
